package ch.ethz.fcl.metrobuzz.render.techniques.focusview;

import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.GLU;

import ch.ethz.fcl.metrobuzz.MBContainer;
import ch.ethz.fcl.metrobuzz.data.singapore.SGInterchange;
import ch.ethz.fcl.metrobuzz.render.interchange.mrt.MRTInterchangeRender;
import ch.ethz.fcl.metrobuzz.render.techniques.clip.Clip;
import ch.ethz.fcl.metrobuzz.render.techniques.projection.Projection;
import ch.ethz.fcl.metrobuzz.spatialindex.object2d.Point2D;
import ch.ethz.fcl.metrobuzz.spatialindex.object2d.Rectangle;
import ch.ethz.fcl.metrobuzz.spatialindex.object3d.Point3D;
import ch.ethz.fcl.metrobuzz.tools.MBGL;

public class FocusViewer {
	private MBContainer container;

	Rectangle mouseBound = null;
	Projection proj;

	Rectangle renderBound = null;
	MRTInterchangeRender mrtRender = null;

	private Point3D mouseLoc = null;
	private Point3D renderCenter = null;

	int detailWidth = 300;
	int detailHeight = 300;

	public FocusViewer(MBContainer container, SGInterchange sr) {
		this.container = container;
		mrtRender = new MRTInterchangeRender(this.container, sr);
		proj = new Projection();
	}

	private void update() {
		mouseBound = proj.getBound(Mouse.getX() - detailWidth / 20,
				Mouse.getY() - detailHeight / 20, Mouse.getX() + detailWidth
						/ 20, Mouse.getY() + detailHeight / 20, 0);

		GL11.glLineWidth(2.0f);
		GL11.glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
		mouseBound.render();

		mouseLoc = proj.getWorldCoord(new Point2D(Mouse.getX(), Mouse.getY()),
				0);

		int width = Display.getWidth(), height = Display.getHeight();
		if (Display.getParent() != null) {
			width = Display.getParent().getWidth();
			height = Display.getParent().getHeight();
		}

		GL11.glViewport(0, 0, width, height);
		GL11.glMatrixMode(GL11.GL_PROJECTION);
		GL11.glPushMatrix();
		GL11.glLoadIdentity();
		GLU.gluPerspective(35, (float) width / (float) height, 0.01f, 10);

		GL11.glMatrixMode(GL11.GL_MODELVIEW);
		GL11.glPushMatrix();
		GL11.glLoadIdentity();
		GLU.gluLookAt(0.0f, 0.0f, 0.09f, 0.0f, -0.0f, 0.0f, 0, 1, 0);

		renderBound = proj.getBound(width - detailWidth, height - detailWidth,
				width, height, 0);

		renderCenter = proj.getWorldCoord(new Point2D(width - detailWidth / 2,
				height - detailHeight / 2), 0);
	}

	public void render() {
		update();
		MBGL.enableBlend();

		GL11.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
		renderBound.render(GL11.GL_POLYGON);

		GL11.glLineWidth(1.0f);

		GL11.glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
		new Rectangle(renderBound.getMinX() - 0.00005f,
				renderBound.getMinY() - 0.00005f,
				renderBound.getMaxX() + 0.00005f,
				renderBound.getMaxY() + 0.00005f).render();

		Point2D mouseNewScreenCoor = proj.getScreenCoord(mouseLoc);

		Point3D mouseNewWorldCoord = proj.getWorldCoord(mouseNewScreenCoor, 0);

		float shiftX = renderCenter.getX() - mouseNewWorldCoord.getX();
		float shiftY = renderCenter.getY() - mouseNewWorldCoord.getY();

		GL11.glTranslatef(shiftX, shiftY, 0f);

		Rectangle rec = new Rectangle(renderBound.getMinX() - shiftX,
				renderBound.getMinY() - shiftY, renderBound.getMaxX() - shiftX,
				renderBound.getMaxY() - shiftY);

		// clip the render area
		Clip.clip(rec);
		mrtRender.render(rec);
		Clip.disableClip();

		GL11.glDisable(GL11.GL_BLEND);

		MBGL.restoreViewMatrix();
	}
}
